#pragma once

#include <string>
#include <map>
#include <utility>
#include <Eigen/Eigen>
#include "SDF.h"

namespace XRwy {

	using HairSimulatorConfDict = std::map<std::string, std::string>;

	struct HairSimulatorConfDictHelperUtility {

		inline bool get_bool(const HairSimulatorConfDict & d, const std::string &key) const {
			std::string value = get_string(d, key);
			if (value == "true")
				return true;
			return false;
		}

		inline std::string get_string(const HairSimulatorConfDict & d, const std::string &key) const {
			return d.find(key)->second;
		}

		inline int get_int(const HairSimulatorConfDict & d, const std::string &key) const {
			return stoi(get_string(d, key));
		}

		inline float get_float(const HairSimulatorConfDict & d, const std::string &key) const {
			return stof(get_string(d, key));
		}
	};

	struct HairSimulatorData {		
		Eigen::Affine3f motion_transform;

		float delta_time;

        //use for collision
        SDFObject *sdf_ptr;
        Eigen::Affine3f sdf_world2local;
	};

	class HairSimulator {
	public:
		HairSimulator() = default;

		//Some simulator might have some preprocess to do before simulation happen
		virtual void preprocess(const HairSimulatorData &) {}

		virtual int get_particle_count() const = 0;
		virtual int get_strand_count() const = 0;
		virtual int get_particle_count_on_strand(int idx) const = 0;
		virtual void copy_particles(float *positions) const = 0;

		virtual void on_frame(const HairSimulatorData &data) = 0;    

		virtual ~HairSimulator() = default;
	};
}